#!/usr/bin/env python
# coding=utf-8

import os, re, datetime, pickle, sys, time, datetime


class bcolors:
	LIGHT_GREEN = '\033[92m'
	LIGHT_YELLOW = '\033[93m'
	LIGHT_PURPLE = '\033[95m'
	LIGHT_BLUE = '\033[94m'
	LIGHT_RED = '\033[91m'
	LIGHT_CYAN = '\033[96m'
	CYAN = '\033[36m'
	BLUE = '\033[34m'
	GREEN = '\033[32m'
	YELLOW = '\033[33m'
	PURPLE = '\033[35m'
	RED = '\033[31m'
	END = '\033[0m'


def user_login():
	'''user login function.
       user floatype , if wrong password three times and locked user.
       userfile: CreditCard.pkl'''

	# 这部分是卡号没有被锁，可以正常登录的情况，用户名和密码两者错误机会只有5次，超过五次，改写控制位，锁定卡
	card_info = pickle.load(open("CreditCard.pkl", "r"))
	card_num = card_info[0]
	card_pass = card_info[1]

	number = int(raw_input(bcolors.LIGHT_YELLOW + "Please input Credit Card number: " + bcolors.END))
	#卡号错误的情况
	if number != card_num:
		sys.exit(bcolors.LIGHT_RED + "card number wrong! " + bcolors.END)

	#这部分是卡号是正确的情况
	else:
		i = 3
		while (i >= 1):
			#控制循环次数，首先重载卡的信息
			card_info = pickle.load(open("CreditCard.pkl", "r"))
			card_num = card_info[0]
			card_pass = card_info[1]
			flag = card_info[2]

			password = raw_input(bcolors.LIGHT_YELLOW + "please input password: " + bcolors.END)

			#卡号正确，密码正确，控制位可登陆，满足三者才可登陆
			if password == card_pass and flag == 'true':
				print bcolors.LIGHT_GREEN + "Yeah, login successful. " + bcolors.END
				break

			#如果卡号密码都正确，控制位false，卡号被锁定，只有账户密码正确的情况下才可进行解锁
			elif password == card_pass and flag == 'false':
				#给予提示选择项判断
				temp_input = raw_input(bcolors.LIGHT_CYAN + "card was locked, press 'unlock' or 'exit' " + bcolors.END)
				if temp_input.lower() == 'unlock':
					unlock()
					break
				elif temp_input.lower() == 'exit':
					sys.exit()

			#密码输入错误的情况下，循环3次，提示可用次数，超过3次，退出循环
			else:
				i -= 1  #循环计数器
				if i:
					print bcolors.RED + "invaild card_pass. \n" + bcolors.END
					continue
				else:
					#一旦用户被锁定，改写控制位，写入文件
					card_info[2] = 'false'
					pickle.dump(card_info, open("CreditCard.pkl", "w"))
					sys.exit(bcolors.LIGHT_RED + "faild three times, card locked. " + bcolors.END)


def reimbursement(info, money):
	'''reimbursement function'''
	card_info = pickle.load(open("CreditCard.pkl", "r"))
	card_balance = card_info[3]
	new_balance = float(card_balance) - float(money) * (-1)  # 还款之后改写余额字段
	card_info[3] = new_balance
	# print card_info, new_balance
	pickle.dump(card_info, open("CreditCard.pkl", "w"))

	# 还款动作写入log文件
	r_state = []
	r_state.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
	r_state.append(' | ' + info + ' | ')
	r_state.append('￥' + str(float(money) * (-1)))
	log_mess = open("CreditCard_state.log", "a")
	log_mess.write(" ".join(r_state) + '\n')
	log_mess.close()

	#友情提示部分
	reim_mess = raw_input(bcolors.LIGHT_CYAN + "reimbursement successful, press any to continue, or EXIT to quit: " + bcolors.END)
	if reim_mess.lower() == 'exit':
		sys.exit()


def get_crash(info, money, charge):
	'''get crash function'''
	# 读取余额，计算手续费，改写余额，重新写入文件
	card_info = pickle.load(open("CreditCard.pkl", "r"))
	card_balance = card_info[3]
	if int(money) > card_balance:
		print bcolors.LIGHT_RED + "low balance, can't get much money. " + bcolors.END
	else:
		new_balance = card_balance - float(money) - float(charge)  #取现之后新的余额
		card_info[3] = new_balance
		pickle.dump(card_info, open('CreditCard.pkl', "w"))

		#写入log文件
		g_state = []
		g_state.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
		g_state.append(' | ' + info + ' | ')
		g_state.append('￥' + str(float(money) + float(charge)))
		log_mess = open("CreditCard_state.log", "a")
		log_mess.write(" ".join(g_state) + '\n')
		log_mess.close()

		#友情提示
		get_mess = raw_input(
			bcolors.LIGHT_CYAN + "reimbursement successful, press any to continue, or EXIT to quit: " + bcolors.END)
		if get_mess.lower() == 'exit':
			sys.exit()


def statement_query():
	'''consume query'''
	print bcolors.LIGHT_PURPLE + "query date format: 'YYYY-mm'" + bcolors.END
	query_time = raw_input(bcolors.LIGHT_YELLOW + "please input query date: " + bcolors.END)
	# 循环遍历文件的每一行，找到日期格式符合用户输入查询的格式，并打印
	all_log = open("CreditCard_state.log", "r").readlines()
	print "=============== statement start ==============="
	for i in all_log:
		if re.findall(query_time, i):
			print i
	print "=============== statement end ==============="


def balance_query():
	'''balance query function'''
	card_info = pickle.load(open("CreditCard.pkl", "r"))
	card_balance = card_info[3]
	print bcolors.LIGHT_GREEN + "current balance: %s" % card_balance + bcolors.END
	con_search = raw_input(bcolors.LIGHT_CYAN + "press any continue, or exit " + bcolors.END)
	if con_search.lower() == 'exit':
		sys.exit(bcolors.LIGHT_CYAN + 'thanks useing, bye-bye~' + bcolors.END)


def write_bill_function(info, money):
	'''write log function, be called by other function
	'''
	w_state = []
	w_state.append(time.strftime('%Y-%m-%d %X', time.localtime(time.time())))
	w_state.append(' | ' + info + ' | ')
	w_state.append('￥' + money)
	log_mess = open("CreditCard_state.log", "a")
	log_mess.write(" ".join(w_state) + '\n')
	log_mess.close()

	# 改写用户余额字段
	temp_info = pickle.load(open("CreditCard.pkl", "r"))
	temp_info[3] -= float(money)
	pickle.dump(temp_info, open("CreditCard.pkl", "w"))


def shopping():
	'''shopping function, operation can write log'''
	# shopping_dict = {'xiaomi':'1999', 'iphone':'4999', 'iwatch':'3499', 'ipad':'2999'}
	# pickle.dump(shopping_dict, open("CreditCard_shopping_list.pkl", "w"))
	while True:
		# 载入信用卡余额
		card_info = pickle.load(open("CreditCard.pkl", "r"))
		card_balance = card_info[3]
		remain = card_balance

		# boughtlist = []	#初始化一个空字典作为购物车

		#读购商品清单字典
		shopping_dict = pickle.load(open("CreditCard_shopping_list.pkl", "r"))
		print "==========shopping list=========="
		for item in shopping_dict:
			print "%s --- %s" % (item, shopping_dict[item])
		print "=================================\n"

		item = raw_input(bcolors.LIGHT_YELLOW + 'which one do you want to buy? ' + bcolors.END).strip()

		#如果用户购买产品不在商品列表，给出提示
		if item not in shopping_dict.keys():
			print bcolors.LIGHT_RED + "item not find %s, please check input" % item + bcolors.END

		#如果用户余额小于商品里价格最低的商品价格，提示余额不足并退出
		elif remain < float(shopping_dict[item]):
			print bcolors.LIGHT_RED + "Sorry, low balance, you can't buy anyone in shopping list. " + bcolors.END
			action_low_balance = raw_input(bcolors.LIGHT_YELLOW + "press any to exit. " + bcolors.END)
			break

		#进入正常购买常规流程
		else:
			#调用写日志的函数进行写state文件
			consume = "bought: %s" % item
			write_bill_function(consume, shopping_dict[item])
			# print consume
			#计算余额
			remain = remain - float(shopping_dict[item])
			#购买商品加入到购物车
			# boughtlist.append(item)

			print "your current balance is: %s" % remain

			#提示用户退出或者继续在购买一次完成之后
			action_curr_balance = raw_input(
				bcolors.LIGHT_CYAN + "press any to continue, or EXIT to quit: " + bcolors.END)
			#忽略掉用户输入大小写，退出打印购物车，否则继续
			if action_curr_balance.lower() == 'exit':
				print bcolors.LIGHT_BLUE + "Thank you for bought, bye-bye." + bcolors.END
				# print bcolors.LIGHT_PURPLE+"the boughtlist: "+bcolors.END
				# for i in boughtlist:
				# 	print "--> " + i, shopping_dict[i]
				break
			continue


def create_bill():
	'''the end day in month create bill'''
	# 计算本月的最后一天，生成账单
	end_day = datetime.date(datetime.date.today().year, datetime.date.today().month + 1, 1) - datetime.timedelta(1)
	if datetime.date.today().day == end_day:
		# if True:
		#账单数据来源是state_log
		bill_source = open("CreditCard_state.log", "r").read()

		#根据特定的格式，找到日志格式中匹配日期，找到匹配的所有本月记录，取出金额进行相加
		if datetime.date.today().month in range(1, 10):
			datetemp = '%s-0%s' % (datetime.date.today().year, datetime.date.today().month)
		# print datetemp
		elif datetime.date.today().month in range(10, 13):
			datetemp = '%s-%s' % (datetime.date.today().year, datetime.date.today().month)
		else:
			pass

		bills = re.findall(datetemp + '[^\n]+', bill_source)
		bill_file_name = "bill-%s.log" % datetemp
		# print '\n'.join(bills)

		#再根据匹配日期抓取最后的金额进行累加操作，得到当前月所有的消费总额，写入以本月命名的文件中
		total = sum([float(i) for i in re.findall(datetemp + '[^￥]+￥([\d\.-]+)', bill_source)])

		c_mess = open(bill_file_name, "w")
		c_mess.write('\n'.join(bills))
		c_mess.write('\n' + "========== total: " + str(total) + " ==========")
		c_mess.close()
	# return "current month has already created. "
	else:
		pass


def unlock():
	'''card unlock function'''
	card_info = pickle.load(open("CreditCard.pkl", "r"))
	card_num = card_info[0]
	card_pass = card_info[1]
	flag = card_info[2]

	number = float(raw_input(bcolors.LIGHT_PURPLE + "Please input card_num: " + bcolors.END))
	# 对卡号进行判断，卡号错误直接不继续进行
	if number != card_num:
		sys.exit(bcolors.RED + "Sorry, Card is wrong, you can't lock card !" + bcolors.END)
	else:
		#卡号正确后，判断控制位，判定卡是否需要解锁
		if flag == 'true':
			print bcolors.RED + "The card wasn't locked, you needn't unlock !" + bcolors.END
			#友情提示部分
			con_search = raw_input(bcolors.LIGHT_BLUE + "press any continue, or exit " + bcolors.END)
			if con_search.lower() == 'exit':
				sys.exit(bcolors.LIGHT_BLUE + 'thanks useing, bye-bye~' + bcolors.END)
		else:
			#需要解锁，改写控制位即可
			card_info[2] = 'true'
			# print card_info[2],flag
			pickle.dump(card_info, open("CreditCard.pkl", "w"))
			con_search = raw_input(bcolors.LIGHT_BLUE + "Already unlock, press any continue, or exit " + bcolors.END)
			if con_search.lower() == 'exit':
				sys.exit()


def arrears_query():
	# if datetime.date.today().day == 11:
	if True:
		# 每到十号进行判断上个月的消费总额，判断当月的消费总额是多少，进入判断
		if datetime.date.today().month in range(1, 10):
			arrears_date = '0%s' % str(datetime.date.today().month - 1)
		elif datetime.date.today().month in range(10, 13):
			arrears_date = '0%s' % str(datetime.date.today().month)
		else:
			pass
		# print "---" +arrears_date
		#累加金额，实际就是本月消费了多少，算作欠款
		bill_source = open("CreditCard_state.log", "r").read()
		total = sum([float(i) for i in re.findall(str(arrears_date) + '[^￥]+￥([\d\.-]+)', bill_source)])
		# print re.findall(str(arrears_date)+'[^￥]+￥([\d\.-]+)', bill_source)
		print "Consumption of this month: %s" % total
		print "amount you owe: %s" % total

	else:
		print "Balance this month has been paid"


if __name__ == '__main__':
	# card_info = [3753, '1q2w', 'false', 15000]
	# pickle.dump(card_info, open("CreditCard.pkl", 'w'))
	user_login()
	create_bill()
	while True:
		print bcolors.LIGHT_GREEN + '''
=== thanks use sample credit card program and  you can type ===
++                      1、balance query                     ++
++                      2、arrears query                        ++
++                      3、get crash                         ++
++                      4、reimbursement                     ++
++                      5、shopping                          ++
++                      6、statement query                   ++
++                      7、login out                         ++
		''' + bcolors.END
		choose = raw_input(bcolors.LIGHT_YELLOW + "please input your choose number: " + bcolors.END)

		if choose == '1':
			balance_query()
		elif choose == '2':
			arrears_query()
		elif choose == '3':
			input_num = raw_input("input crash num: ")
			charge = float(input_num) * 0.05
			info_mess = "Get crash %s, charge %s " % (input_num, charge)
			get_crash(info_mess, input_num, charge)
		elif choose == '4':
			input_num = raw_input("input reimbursement number: ")
			info_mess = "reimbursement %s" % input_num
			reimbursement(info_mess, input_num)
		elif choose == '5':
			shopping()
		elif choose == '6':
			statement_query()
		elif choose == '7':
			sys.exit(bcolors.LIGHT_CYAN + "Thank you for useing. Bye-Bye~\n" + bcolors.END)
		else:
			print bcolors.RED + "Sorry, error input, please try again. " + bcolors.END